package net.oschina.allchat.server.framework.core.internal;

import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import net.oschina.allchat.server.framework.core.IApplication;
import net.oschina.allchat.server.framework.core.IService;
import net.oschina.allchat.server.framework.core.config.IApplicationConfiguration;
import net.oschina.allchat.server.framework.core.internal.repository.Repository;
import net.oschina.allchat.server.framework.core.repository.IComponentCollector;
import net.oschina.allchat.server.framework.core.repository.IServiceListener;
import net.oschina.allchat.server.framework.core.repository.IServiceWrapper;

import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Application implements IApplication, IServiceListener {

	private static final Logger logger = LoggerFactory.getLogger(Application.class);
	
	private IApplicationConfiguration appConfiguration;
	
	private BundleContext bundleContext;
	
	private Repository repository;
	
	private Map<String, IService> services;
	
	private ServiceRegistration<IComponentCollector> srComponentCollector;
	
	public Application(BundleContext bundleContext, IApplicationConfiguration appConfiguration) {
		this.bundleContext = bundleContext;
		services = new HashMap<String, IService>();
		
		this.appConfiguration = appConfiguration;
	}
	
	@Override
	public void start() {
		repository = new Repository(bundleContext, appConfiguration);
		repository.addServiceListener(this);
		repository.init();
		
		Dictionary<String, Object> properties = new Hashtable<String, Object>();
		properties.put(Constants.SERVICE_INTENTS, ALLCHAT_FRAMEWORK_COMPONENT_COLLECTOR);
		srComponentCollector = bundleContext.registerService(IComponentCollector.class, repository, properties);
		
		logger.info("AllChat application started");
	}
	
	@Override
	public void stop() {
		srComponentCollector.unregister();
		repository.destroy();
		
		logger.info("AllChat application stopped");
	}

	@Override
	public IApplicationConfiguration getConfiguration() {
		return appConfiguration;
	}

	@Override
	public void available(IServiceWrapper serviceWrapper) {
		for (String serviceId : appConfiguration.getDisabledServices()) {
			if (serviceWrapper.getId().equals(serviceId)) {
				logger.info(String.format("serivce '%s' is available. but we don't start it because it's disabled",
						serviceId));
				return;
			}
		}
		
		try {
			IService service = serviceWrapper.create();
			services.put(serviceWrapper.getId(), service);
			service.start();
			
			logger.info(String.format("service '%s' has started", serviceWrapper.getId()));
		} catch (Exception e) {
			logger.error(String.format("can't start service %s", serviceWrapper.getId()), e);
		}
	}

	@Override
	public void unavailable(String serviceId) {
		IService service = services.get(serviceId);
		if (service != null) {
			try {
				service.stop();
				logger.info(String.format("service '%s' has stopped", serviceId));
			} catch (Exception e) {
				logger.error(String.format("can't stop service %s", serviceId), e);
			}
		}
	}
	
}
